/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.cashmate.struts;

import com.cashmate.hibernate.dao.AreaDAO;
import com.cashmate.hibernate.dao.BranchDAO;
import com.cashmate.hibernate.dao.DccrDAO;
import com.cashmate.hibernate.dao.PastDueListingDAO;
import com.cashmate.hibernate.pojo.Areas;
import com.cashmate.hibernate.pojo.Employees;
import com.cashmate.hibernate.pojo.Pastduelisting;
import com.cashmate.hibernate.pojo.Performance;
import com.cashmate.utilities.ClassUtils;
import com.cashmate.utilities.PerformanceObject;
import com.cashmate.utilities.Utils;
import com.opensymphony.xwork2.ActionSupport;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Result;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;

/**
 *
 * @author Dean
 */
@Result(name = "error", type = "redirect", location = "/error/messages.jsp")
public class GridMonthperf extends ActionSupport {

    private Logger logger = Logger.getLogger(GridMonthperf.class);
    private List<PerformanceObject> gridModel;
    //get how many rows we want to have into the grid - rowNum attribute in the grid
    private Integer rows = 0;
    //Get the requested page. By default grid sets this to 1.
    private Integer page = 0;
    // sorting order - asc or desc
    private String sord;
// get index row - i.e. user click to sort.
    private String sidx;
    // Search Field
    private String searchField;
    // The Search String
    private String searchString;
    // he Search Operation ['eq','ne','lt','le','gt','ge','bw','bn','in','ni','ew','en','cn','nc']
    private String searchOper;
    // Your Total Pages
    private Integer total = 0;
    // All Record
    private Integer records = 0;
    private String month, year, branchid, type;
    private final AreaDAO areadao = (AreaDAO) ServletActionContext.getServletContext().getAttribute("areaDAO");
    private final BranchDAO bdao = (BranchDAO) ServletActionContext.getServletContext().getAttribute("branchDAO");
    private final DccrDAO dccrdao = (DccrDAO) ServletActionContext.getServletContext().getAttribute("dccrDAO");
    private final PastDueListingDAO pastdao = (PastDueListingDAO) ServletActionContext.getServletContext().getAttribute("pastdao");
    //    private final Branches b = (Branches) ServletActionContext.getRequest().getSession().getAttribute("branch");
//    private final Usertypes ut = (Usertypes) ServletActionContext.getRequest().getSession().getAttribute("usertype");

    public GridMonthperf() {
    }

    @Action(value = "/grid-monthperf", results = {
        @Result(name = "success", type = "json")
    })
    @Override
    public String execute() throws Exception {
        try {
            logger.info(ClassUtils.toString(this));
            //max record
            int to = (rows * page);
            //offset record
//            int from = to - rows;
            //instantiate a new criteria for a POJO class
            int branchid_i = Integer.parseInt(branchid);
            int mont_i = Integer.parseInt(month);
            int year_i = Integer.parseInt(year);

            String areacode = null;

            if (searchField != null && searchField.length() > 0) {
                if (searchField.equals("areacode")) {
                    areacode = searchString;
                }
            }

            DetachedCriteria criter = DetachedCriteria.forClass(Pastduelisting.class);
            criter.add(Restrictions.eq("branchid", branchid_i));
            if (areacode != null) {
                criter.add(Restrictions.eq("areacode", "%" + areacode + "%"));
            }

            List<Performance> tempList = dccrdao.monthlyPerformanceProcedure(mont_i, year_i, branchid_i, areacode);
            gridModel = new LinkedList<PerformanceObject>();
            List<Pastduelisting> pastDue = new LinkedList<Pastduelisting>();
            PerformanceObject nm = new PerformanceObject();
            nm.setAreacode("NM");

            if (!type.equals("RTNG")) {
                pastDue = pastdao.findByCriteria(criter);
            }

            for (Areas a : areadao.getAreasPerBranch(branchid_i)) {
                //System.out.println(a.getAreacode());
                PerformanceObject po = null;
                if (areacode == null) {
                    po = new PerformanceObject();
                    po.setAreacode(a.getAreacode());
                } else if (a.getAreacode().contains(areacode)) {
                    po = new PerformanceObject();
                    po.setAreacode(a.getAreacode());
                }
                if (po != null) {
                    for (Performance p : tempList) {
                        //System.out.println(ClassUtils.toString(p));
                        if (p.getAreacode().equals(a.getAreacode())) {
                            String date = p.getDategenerated();
                            if (type.equals("DUE")) {
                                if (Utils.isFirstCut(date)) {
                                    po.setFirstcut(p.getCutoffdue());
                                } else if (Utils.isSecondCut(date)) {
                                    po.setSecondcut(p.getCutoffdue());
                                } else if (Utils.isThirdCut(date)) {
                                    po.setThirdcut(p.getCutoffdue());
                                } else if (Utils.isFourthCut(date)) {
                                    po.setFourthcut(p.getCutoffdue());
                                } else if (Utils.isFifthCut(date)) {
                                    po.setFifthcut(p.getCutoffdue());
                                }
                            } else if (type.equals("TCC")) {
                                if (Utils.isFirstCut(date)) {
                                    po.setFirstcut(p.getTotalcutoffcollection());
                                } else if (Utils.isSecondCut(date)) {
                                    po.setSecondcut(p.getTotalcutoffcollection());
                                } else if (Utils.isThirdCut(date)) {
                                    po.setThirdcut(p.getTotalcutoffcollection());
                                } else if (Utils.isFourthCut(date)) {
                                    po.setFourthcut(p.getTotalcutoffcollection());
                                } else if (Utils.isFifthCut(date)) {
                                    po.setFifthcut(p.getTotalcutoffcollection());
                                }
                            } else if (type.equals("TP")) {
                                if (Utils.isFirstCut(date)) {
                                    po.setFirstcut(p.getTotalpayment());
                                } else if (Utils.isSecondCut(date)) {
                                    po.setSecondcut(p.getTotalpayment());
                                } else if (Utils.isThirdCut(date)) {
                                    po.setThirdcut(p.getTotalpayment());
                                } else if (Utils.isFourthCut(date)) {
                                    po.setFourthcut(p.getTotalpayment());
                                } else if (Utils.isFifthCut(date)) {
                                    po.setFifthcut(p.getTotalpayment());
                                }
                            } else if (type.equals("DPO")) {
                                if (Utils.isFirstCut(date)) {
                                    po.setFirstcut(p.getDueplusod());
                                } else if (Utils.isSecondCut(date)) {
                                    po.setSecondcut(p.getDueplusod());
                                } else if (Utils.isThirdCut(date)) {
                                    po.setThirdcut(p.getDueplusod());
                                } else if (Utils.isFourthCut(date)) {
                                    po.setFourthcut(p.getDueplusod());
                                } else if (Utils.isFifthCut(date)) {
                                    po.setFifthcut(p.getDueplusod());
                                }
                            } else if (type.equals("OD")) {
                                if (Utils.isFirstCut(date)) {
                                    po.setFirstcut(p.getOverdue());
                                } else if (Utils.isSecondCut(date)) {
                                    po.setSecondcut(p.getOverdue());
                                } else if (Utils.isThirdCut(date)) {
                                    po.setThirdcut(p.getOverdue());
                                } else if (Utils.isFourthCut(date)) {
                                    po.setFourthcut(p.getOverdue());
                                } else if (Utils.isFifthCut(date)) {
                                    po.setFifthcut(p.getOverdue());
                                }
                            } else if (type.equals("RTNG")) {
                                if (Utils.isFirstCut(date)) {
                                    po.setFirstcut(Utils.roundToDecimals(p.getRating(), 2));
                                } else if (Utils.isSecondCut(date)) {
                                    po.setSecondcut(Utils.roundToDecimals(p.getRating(), 2));
                                } else if (Utils.isThirdCut(date)) {
                                    po.setThirdcut(Utils.roundToDecimals(p.getRating(), 2));
                                } else if (Utils.isFourthCut(date)) {
                                    po.setFourthcut(Utils.roundToDecimals(p.getRating(), 2));
                                } else if (Utils.isFifthCut(date)) {
                                    po.setFifthcut(Utils.roundToDecimals(p.getRating(), 2));
                                }
                            }
                        }
                    }
                    if (pastDue.size() > 0) {
                        for (Pastduelisting p : pastDue) {
                            if (p.getAreacode().equals(a.getAreacode())) {
                                String date = p.getDateofpdl();
                                if (type.equals("DUE")) {
                                    if (Utils.isLesser(date, mont_i, year_i, 1)) {
                                        nm.setFirstcut(nm.getFirstcut() + p.getCutoffdue());
                                    }
                                    if (Utils.isLesser(date, mont_i, year_i, 2)) {
                                        nm.setSecondcut(nm.getSecondcut() + p.getCutoffdue());
                                    }
                                    if (Utils.isLesser(date, mont_i, year_i, 3)) {
                                        nm.setThirdcut(nm.getThirdcut() + p.getCutoffdue());
                                    }
                                    if (Utils.isLesser(date, mont_i, year_i, 4)) {
                                        nm.setFourthcut(nm.getFourthcut() + p.getCutoffdue());
                                    }
                                    if (Utils.isLesser(date, mont_i, year_i, 5)) {
                                        nm.setFifthcut(nm.getFifthcut() + p.getCutoffdue());
                                    }
                                } else if (type.equals("TCC")) {
                                    if (Utils.isLesser(date, mont_i, year_i, 1)) {
                                        nm.setFirstcut(nm.getFirstcut() + p.getTotalcutoffcollection());
                                    }
                                    if (Utils.isLesser(date, mont_i, year_i, 2)) {
                                        nm.setSecondcut(nm.getSecondcut() + p.getTotalcutoffcollection());
                                    }
                                    if (Utils.isLesser(date, mont_i, year_i, 3)) {
                                        nm.setThirdcut(nm.getThirdcut() + p.getTotalcutoffcollection());
                                    }
                                    if (Utils.isLesser(date, mont_i, year_i, 4)) {
                                        nm.setFourthcut(nm.getFourthcut() + p.getTotalcutoffcollection());
                                    }
                                    if (Utils.isLesser(date, mont_i, year_i, 5)) {
                                        nm.setFifthcut(nm.getFifthcut() + p.getTotalcutoffcollection());
                                    }
                                } else if (type.equals("DPO")) {
                                    if (Utils.isLesser(date, mont_i, year_i, 1)) {
                                        nm.setFirstcut(nm.getFirstcut() + p.getDueplusod());
                                    }
                                    if (Utils.isLesser(date, mont_i, year_i, 2)) {
                                        nm.setSecondcut(nm.getSecondcut() + p.getDueplusod());
                                    }
                                    if (Utils.isLesser(date, mont_i, year_i, 3)) {
                                        nm.setThirdcut(nm.getThirdcut() + p.getDueplusod());
                                    }
                                    if (Utils.isLesser(date, mont_i, year_i, 4)) {
                                        nm.setFourthcut(nm.getFourthcut() + p.getDueplusod());
                                    } else if (Utils.isLesser(date, mont_i, year_i, 5)) {
                                        nm.setFifthcut(nm.getFifthcut() + p.getDueplusod());
                                    }
                                } else if (type.equals("OD")) {
                                    if (Utils.isLesser(date, mont_i, year_i, 1)) {
                                        nm.setFirstcut(nm.getFirstcut() + p.getOverdue());
                                    }
                                    if (Utils.isLesser(date, mont_i, year_i, 2)) {
                                        nm.setSecondcut(nm.getSecondcut() + p.getOverdue());
                                    }
                                    if (Utils.isLesser(date, mont_i, year_i, 3)) {
                                        nm.setThirdcut(nm.getThirdcut() + p.getOverdue());
                                    }
                                    if (Utils.isLesser(date, mont_i, year_i, 4)) {
                                        nm.setFourthcut(nm.getFourthcut() + p.getOverdue());
                                    }
                                    if (Utils.isLesser(date, mont_i, year_i, 5)) {
                                        nm.setFifthcut(nm.getFifthcut() + p.getOverdue());
                                    }
                                }
                            }
                        }
                    }
                    if (!gridModel.contains(po)) {
                        //System.out.println(ClassUtils.toString(po));
                        gridModel.add(po);
                    }
                }
            }

            // handle Order By
            if (sidx != null && !sidx.equals("")) {
                if (sord.equals("asc")) {
                    Collections.sort(gridModel, new PerformanceComparator(sidx));
                } else {
                    Collections.sort(gridModel, new PerformanceComparator(sidx));
                    Collections.reverse(gridModel);
                }
            }

            if (!type.equals("RTNG")) {
                PerformanceObject active = new PerformanceObject();
                active.setAreacode("Active");
                for (PerformanceObject po : gridModel) {
                    active.setFirstcut(active.getFirstcut() + po.getFirstcut());
                    active.setSecondcut(active.getSecondcut() + po.getSecondcut());
                    active.setThirdcut(active.getThirdcut() + po.getThirdcut());
                    active.setFourthcut(active.getFourthcut() + po.getFourthcut());
                    active.setFifthcut(active.getFifthcut() + po.getFifthcut());
                }

                PerformanceObject tot = new PerformanceObject();
                tot.setAreacode("Total");
                tot.setFirstcut(nm.getFirstcut() + active.getFirstcut());
                tot.setSecondcut(nm.getSecondcut() + active.getSecondcut());
                tot.setThirdcut(nm.getThirdcut() + active.getThirdcut());
                tot.setFourthcut(nm.getFourthcut() + active.getFourthcut());
                tot.setFifthcut(nm.getFifthcut() + active.getFifthcut());

                gridModel.add(nm);
                gridModel.add(active);
                gridModel.add(tot);
            } else {
                gridModel.add(computeOverAll(tempList));
            }
            HashMap<String, List<PerformanceObject>> monthExportMap = null;
            if (null == ServletActionContext.getRequest().getSession().getAttribute("monthexport")) {
                monthExportMap = new HashMap<String, List<PerformanceObject>>();
            } else {
                monthExportMap = (HashMap<String, List<PerformanceObject>>) ServletActionContext.getRequest().getSession().getAttribute("monthexport");
            }
            monthExportMap.put(type, gridModel);

            ServletActionContext.getRequest().getSession().setAttribute("monthdetails", month + "-" + year + "-" + bdao.get(Integer.parseInt(branchid)).getBranchcode());
            ServletActionContext.getRequest().getSession().setAttribute("monthexport", monthExportMap);
            records = gridModel.size();
            total = records;
            //logger.info(ClassUtils.toString(this));
        } catch (Exception ex) {
            Employees emps = (Employees) ServletActionContext.getRequest().getSession().getAttribute("employee");
            if (emps != null) {
                logger.fatal("(" + emps.getIdnumber() + "):" + ex.getLocalizedMessage(), ex);
            } else {
                logger.fatal(ex.getLocalizedMessage(), ex);
            }
            ex.printStackTrace();
            addActionError(ex.getLocalizedMessage());
            return ERROR;
        } finally {
            DccrDAO.close();
            AreaDAO.close();
            PastDueListingDAO.close();
            BranchDAO.close();
        }
        return SUCCESS;
    }

    public PerformanceObject computeOverAll(List<Performance> performanceList) {
        PerformanceObject overall = new PerformanceObject();
        overall.setAreacode("Overall");
        Map<String, double[]> ratingValues = new HashMap<String, double[]>();
        for (Performance p : performanceList) {
            if (Utils.isFirstCut(p.getDategenerated())) {
                if (!ratingValues.containsKey("first")) {
                    double[] val = new double[3];
                    val[0] += p.getCutoffdue();
                    val[1] += p.getDueplusod();
                    val[2] += p.getOverdue();
                    ratingValues.put("first", val);
                } else {
                    ratingValues.get("first")[0] += p.getCutoffdue();
                    ratingValues.get("first")[1] += p.getDueplusod();
                    ratingValues.get("first")[2] += p.getOverdue();
                }
            } else if (Utils.isSecondCut(p.getDategenerated())) {
                if (!ratingValues.containsKey("second")) {
                    double[] val = new double[3];
                    val[0] += p.getCutoffdue();
                    val[1] += p.getDueplusod();
                    val[2] += p.getOverdue();
                    ratingValues.put("second", val);
                } else {
                    ratingValues.get("second")[0] += p.getCutoffdue();
                    ratingValues.get("second")[1] += p.getDueplusod();
                    ratingValues.get("second")[2] += p.getOverdue();
                }
            } else if (Utils.isThirdCut(p.getDategenerated())) {
                if (!ratingValues.containsKey("third")) {
                    double[] val = new double[3];
                    val[0] += p.getCutoffdue();
                    val[1] += p.getDueplusod();
                    val[2] += p.getOverdue();
                    ratingValues.put("third", val);
                } else {
                    ratingValues.get("third")[0] += p.getCutoffdue();
                    ratingValues.get("third")[1] += p.getDueplusod();
                    ratingValues.get("third")[2] += p.getOverdue();
                }
            } else if (Utils.isFourthCut(p.getDategenerated())) {
                if (!ratingValues.containsKey("fourth")) {
                    double[] val = new double[3];
                    val[0] += p.getCutoffdue();
                    val[1] += p.getDueplusod();
                    val[2] += p.getOverdue();
                    ratingValues.put("fourth", val);
                } else {
                    ratingValues.get("fourth")[0] += p.getCutoffdue();
                    ratingValues.get("fourth")[1] += p.getDueplusod();
                    ratingValues.get("fourth")[2] += p.getOverdue();
                }
            } else if (Utils.isFifthCut(p.getDategenerated())) {
                if (!ratingValues.containsKey("fifth")) {
                    double[] val = new double[3];
                    val[0] += p.getCutoffdue();
                    val[1] += p.getDueplusod();
                    val[2] += p.getOverdue();
                    ratingValues.put("fifth", val);
                } else {
                    ratingValues.get("fifth")[0] += p.getCutoffdue();
                    ratingValues.get("fifth")[1] += p.getDueplusod();
                    ratingValues.get("fifth")[2] += p.getOverdue();
                }
            }
        }
        if (ratingValues.size() >= 1) {
            overall.setFirstcut(Utils.roundToDecimals((ratingValues.get("first")[1] / (ratingValues.get("first")[0] + ratingValues.get("first")[2])) * 100, 2));
            System.out.println(overall.getFirstcut());
        }
        if (ratingValues.size() >= 2) {
            overall.setSecondcut(Utils.roundToDecimals((ratingValues.get("second")[1] / (ratingValues.get("second")[0] + ratingValues.get("second")[2])) * 100, 2));
            System.out.println(overall.getSecondcut());
        }
        if (ratingValues.size() >= 3) {
            overall.setThirdcut(Utils.roundToDecimals((ratingValues.get("third")[1] / (ratingValues.get("third")[0] + ratingValues.get("third")[2])) * 100, 2));
            System.out.println(overall.getThirdcut());
        }
        if (ratingValues.size() >= 4) {
            overall.setFourthcut(Utils.roundToDecimals((ratingValues.get("fourth")[1] / (ratingValues.get("fourth")[0] + ratingValues.get("fourth")[2])) * 100, 2));
            System.out.println(overall.getFourthcut());
        }
        if (ratingValues.size() >= 5) {
            overall.setFifthcut(Utils.roundToDecimals((ratingValues.get("fifth")[1] / (ratingValues.get("fifth")[0] + ratingValues.get("fifth")[2])) * 100, 2));
            System.out.println(overall.getFifthcut());
        }
        return overall;
    }

    public List<PerformanceObject> getGridModel() {
        return gridModel;
    }

    public void setGridModel(List<PerformanceObject> gridModel) {
        this.gridModel = gridModel;
    }

    public Integer getPage() {
        return page;
    }

    public void setPage(Integer page) {
        this.page = page;
    }

    public Integer getRecords() {
        return records;
    }

    public void setRecords(Integer records) {
        this.records = records;
    }

    public Integer getRows() {
        return rows;
    }

    public void setRows(Integer rows) {
        this.rows = rows;
    }

    public String getSearchField() {
        return searchField;
    }

    public void setSearchField(String searchField) {
        this.searchField = searchField;
    }

    public String getSearchOper() {
        return searchOper;
    }

    public void setSearchOper(String searchOper) {
        this.searchOper = searchOper;
    }

    public String getSearchString() {
        return searchString;
    }

    public void setSearchString(String searchString) {
        this.searchString = searchString;
    }

    public String getSidx() {
        return sidx;
    }

    public void setSidx(String sidx) {
        this.sidx = sidx;
    }

    public String getSord() {
        return sord;
    }

    public void setSord(String sord) {
        this.sord = sord;
    }

    public Integer getTotal() {
        return total;
    }

    public void setTotal(Integer total) {
        this.total = total;
    }

    public void setBranchid(String branchid) {
        this.branchid = branchid;
    }

    public void setMonth(String month) {
        this.month = month;
    }

    public void setYear(String year) {
        this.year = year;
    }

    public void setType(String type) {
        this.type = type;
    }
}

class PerformanceComparator implements Comparator<PerformanceObject> {

    private String token;

    public PerformanceComparator(String token) {
        this.token = token;
    }

    public int compare(PerformanceObject t, PerformanceObject t1) {
        if (token.equals("firstcut")) {
            return diffDouble(t.getFirstcut(), t1.getFirstcut());
        } else if (token.equals("secondcut")) {
            return diffDouble(t.getSecondcut(), t1.getSecondcut());
        } else if (token.equals("thirdcut")) {
            return diffDouble(t.getThirdcut(), t1.getThirdcut());
        } else if (token.equals("fourthcut")) {
            return diffDouble(t.getFourthcut(), t1.getFourthcut());
        } else if (token.equals("fifthcut")) {
            return diffDouble(t.getFifthcut(), t1.getFifthcut());
        } else if (token.equals("totalperarea")) {
            return diffDouble(t.getTotalperarea(), t1.getTotalperarea());
        } else {
            return t.getAreacode().compareTo(t1.getAreacode());
        }
    }

    private int diffDouble(double d1, double d2) {
        if (d1 > d2) {
            return 1;
        } else if (d1 < d2) {
            return -1;
        } else {
            return 0;
        }
    }
}
